/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Parser;

import lowlevel.BasicBlock;
import lowlevel.Function;
import lowlevel.Operand;
import lowlevel.Operation;

/**
 *
 * @author maxmuhlenkamp
 */
public class ReturnStmt extends Statement {
    Expression expr;
    
    public ReturnStmt(Expression expr){
        this.expr = expr;
    }

    @Override
    void print(String indent) {
        CMinusParser.oFile.println(indent + "ReturnStmt:");
        CMinusParser.oFile.println(indent + "  return");
        if(expr != null){
            expr.print(indent + "  ");
        }
        else{
            CMinusParser.oFile.println(indent + "    null");
        }
        CMinusParser.oFile.flush();
    }

    @Override
    void genLLCode(Function func) {
        BasicBlock currentBlock = func.getCurrBlock();
        
        if(expr != null){
            expr.genLLCode(func);
            
            Operation ret = new Operation(Operation.OperationType.ASSIGN, currentBlock);
            Operand dest0 = new Operand(Operand.OperandType.MACRO, "RetReg");
            Operand src0 = new Operand(Operand.OperandType.REGISTER, expr.getRegNum());
            ret.setSrcOperand(0, src0);
            ret.setDestOperand(0, dest0);
            func.getCurrBlock().appendOper(ret);
        }
        
        // create exit block if necessary
        if(func.getReturnBlock() == null){
            func.genReturnBlock();
        }
        
        // create jump to exit block
        Operation jmp = new Operation(Operation.OperationType.JMP, currentBlock);
        Operand src = new Operand(Operand.OperandType.BLOCK, func.getReturnBlock().getBlockNum());
        jmp.setSrcOperand(0, src);
        currentBlock.appendOper(jmp);
    }
}
